package org.az.netty_study.p03_nio组件之selector._2_单线程的非阻塞模式;

import lombok.extern.slf4j.Slf4j;
import org.az.netty_study.ByteBufferUtil;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;

/**
 * 下面演示了单线程的非阻塞服务器
 */
@Slf4j
public class Server {
    public static void main(String[] args) throws IOException {
        ByteBuffer buffer = ByteBuffer.allocate(16);
        ServerSocketChannel ssc = ServerSocketChannel.open();
        /**
         * 下面代码将服务器改成非阻塞模式
         * 此时ssc.accept()会变成非阻塞，也就是没有连接建立时，程序也会继续往下运行，同时方法返回的null
         */
        ssc.configureBlocking(false);
        ssc.bind(new InetSocketAddress(9998));
        List<SocketChannel> channels = new ArrayList<>();
        while (true) {
            //log.info("connecting...");
            //就算没有连接，该方法也不会阻塞，同时返回一个null
            SocketChannel sc = ssc.accept();
            //不为null时，表示有连接建立
            if (sc != null) {
                log.info("connected...{}", sc);
                channels.add(sc);
                /**
                 * 下面代码SocketChannel设为非阻塞模式
                 * 同理，当SocketChannel没有发生可读事件时，该方法也不会阻塞，而是会继续运行，同时返回0
                 */
                sc.configureBlocking(false);
            }
            for (SocketChannel channel : channels) {
                //log.info("before read...{}", channel);
                //就算没有可读事件，该方法也不会阻塞,通过方法返回值为0
                int read = channel.read(buffer);
                //read不为0时，表示发生了可读事件
                if (read > 0) {
                    buffer.flip();
                    ByteBufferUtil.debugAll(buffer);
                    buffer.clear();
                    log.info("after read...{}", channel);
                }
            }

        }
        /**
         * 单线程的非阻塞模式会一直不断的运行，可以处理连接事件和可读事件
         * 这种模式的问题也很明显，当没有连接和可读事件发生时，while (true)会一直死循环，白白浪费cpu
         */
    }
}
